package com.diaohw.platform.framework.db.flex.config;

import cn.hutool.core.util.ClassUtil;
import com.diaohw.platform.common.constant.ServiceConstant;
import com.diaohw.platform.common.util.JacksonUtil;
import com.diaohw.platform.framework.db.flex.listener.GlobalInsertListener;
import com.diaohw.platform.framework.db.flex.listener.GlobalUpdateListener;
import com.diaohw.platform.framework.db.flex.obj.model.BaseModel;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mybatisflex.annotation.Table;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.handler.JacksonTypeHandler;
import com.mybatisflex.core.mybatis.FlexConfiguration;
import com.mybatisflex.spring.boot.ConfigurationCustomizer;
import com.mybatisflex.spring.boot.MyBatisFlexCustomizer;
import jakarta.annotation.PostConstruct;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import java.util.Set;
import java.util.stream.Collectors;

@Configuration
@MapperScan("com.diaohw.*.**.mapper")
public class DbConfig implements MyBatisFlexCustomizer, ConfigurationCustomizer {

    Logger logger = LoggerFactory.getLogger("SQL Statistics");


    @PostConstruct
    public void initial() {
        ObjectMapper objectMapper = JacksonUtil.createObjectMapper();
        logger.info("JacksonTypeHandler ObjectMapper is used JsonUtil.createObjectMapper()");
        JacksonTypeHandler.setObjectMapper(objectMapper);

//        if (!properties.isDb()) {
//            return;
//        }
        AuditManager.setAuditEnable(true);

        AuditManager.setMessageCollector(auditManage -> {
            logger.info("Elapsed Time {} ms, SQL: {}", auditManage.getElapsedTime(), auditManage.getFullSql());
        });


    }

    @Override
    public void customize(FlexConfiguration configuration) {
        // 在这里为 configuration 进行配置
        configuration.setLogImpl(StdOutImpl.class);
    }

    @Override
    public void customize(FlexGlobalConfig flexGlobalConfig) {

        Class<?>[] baseModelClass = getModelClass();
        flexGlobalConfig.registerInsertListener(new GlobalInsertListener(), baseModelClass);
        flexGlobalConfig.registerUpdateListener(new GlobalUpdateListener(), baseModelClass);
    }

    private Class<?>[] getModelClass() {
        Set<Class<?>> classes = ClassUtil.scanPackage(ServiceConstant.basePackage)
                .stream().filter(clazz -> {
                    boolean allAssignableFrom = clazz.isAnnotationPresent(Table.class);
                    //要将 本身排除
                    return allAssignableFrom && clazz != BaseModel.class;
                }).collect(Collectors.toSet());

        logger.info("{} >>> {}", BaseModel.class, classes.size());

        return classes.toArray(new Class<?>[0]);


    }

}
